/* eslint-disable no-undef */
/**
 * Promise 的基本格式是 new Promise(function(successFun,failFn) { (successFn | failFn )(returnData) })
 * 代码中仅有两处使用到 new Promise
 * 如果有必要可以改写此两处，推荐做法为
 * (new Promise(s,f) => {}).catch()
 * 不过前提是错误事件是可以同意处理的
 */
const defaultFetchEvent =
    args =>
        new Promise((s, f) => {
            fetchEvent.fetchEventApi(args, ({ err, data }) => {
                if (err) {
                    f({ err, data });
                } else {
                    s(data);
                }
            });
        });

const onlySuccessPromise = (ev, args) => new Promise((s) => {
    ev(s, ...args);
});
const projectSettingFileName = 'setting.json';
const __config__ = {
    defaultMysqlSetting: {
        host: '127.0.0.1',
        user: 'root',
        password: 'root',
        database: 'db',
    },
    defaultProjectSetting: {
        smbDisk: 'Z',
    },
    root() {
        return fetchEvent.extendMethod.paths.projectRoot;
    },
    projectSetting() {
        return fetchEvent.extendMethod.path.join(fetchEvent.extendMethod.paths.projectRoot, projectSettingFileName);
    },
    getProjectConfig() {
        const path = __config__.projectSetting();
        return fetchEventUtils.file.existsWithReadOrCreate(
            path,
            JSON.stringify(__config__.defaultProjectSetting));
    },
};

function* asyncGetFetchData(x) {
    const defaultObj = {
        data: '',
        err: '',
    };
    let nextx = true;
    const datas = [];
    let suc = null;
    let fail = null;
    while (nextx) {
        nextx = yield x;
        if (nextx instanceof Function) {
            if (suc) {
                fail = nextx;
            } else {
                suc = nextx;
            }
        } else if (typeof nextx === 'object') {
            nextx = Object.assign({}, defaultObj, nextx);
            if (nextx.err) {
                fail(nextx);
                break;
            } else {
                datas.push(nextx.data);
            }
        } else {
            break;
        }
    }
    return suc(datas);
}

const defaultAsyncFetchEvent =
    (args) => {
        const asyncGetFetchDataObj = asyncGetFetchData(0);
        top.loading = true;
        return new Promise((s, f) => {
            asyncGetFetchDataObj.next(0);
            asyncGetFetchDataObj.next(s);
            asyncGetFetchDataObj.next(f);
            fetchEvent.fetchEventApi(args, (obj) => {
                setTimeout(() => {
                    asyncGetFetchDataObj.next(obj);
                });
            });
        })
            .catch(({ err }) => {
                message.error(err);
            });
    };

export const fetchEventUtils = {
    dir: {
        defaultEvent: (eventName, path) => {
            const dir = fetchEvent.fetchEventAction.dir[eventName]();
            dir.param.path = path;
            return dir;
        },
        getFilesUnderPath: (path, ext, withInfo) => {
            const dir = fetchEvent.fetchEventAction.dir.getFilesUnderPath();
            ext = ext || [];
            dir.param = {
                path,
                ext: (ext instanceof Array ? ext : [ext]),
                withInfo: !!withInfo,
            };
            return defaultFetchEvent(dir);
        },
        isEmpty: path => defaultFetchEvent(fetchEventUtils.dir.defaultEvent('isEmpty', path)),
        getAll: (path, childPath, isTree, excludePath) => {
            const dirs = fetchEvent.fetchEventAction.dir.getAll();
            dirs.param = {
                path, childPath, isTree, excludePath,
            };
            return defaultFetchEvent(dirs);
        },
        mkdir: path => defaultFetchEvent(fetchEventUtils.dir.defaultEvent('mkdir', path)),
        removeFileOrDir: path => defaultFetchEvent(fetchEventUtils.dir.defaultEvent('removeFileOrDir', path)),
        checkFoldersExsit: (paths) => {
            const dirs = fetchEvent.fetchEventAction.dir.checkFoldersExsit();
            dirs.param.folders = paths;
            return defaultFetchEvent(dirs);
        },
        copyDirSync: (src, dist, root) => {
            const cpDir = fetchEvent.fetchEventAction.dir.copyDirSync();
            cpDir.param = {
                src,
                dist,
                root,
            };
            return defaultFetchEvent(cpDir);
        },
        copyDir: (src, dist, root) => {
            const cpDir = fetchEvent.fetchEventAction.dir.copyDir();
            cpDir.param = {
                src,
                dist,
                root,
            };
            // fetchEvent.fetchEventApi(cpDir, cb);
            return defaultAsyncFetchEvent(cpDir);
        },
    },
    __async__: {
        dir: {
            copyDir: (cb, src, dist, root) => {
                const cpDir = fetchEvent.fetchEventAction.dir.copyDir();
                cpDir.param = {
                    src,
                    dist,
                    root,
                };
                fetchEvent.fetchEventApi(cpDir, cb);
            },
        },
    },
    file: {
        defaultEvent: (eventName, fileName, content, binary) => {
            const file = fetchEvent.fetchEventAction.file[eventName]();
            file.param = {
                fileName,
                content: content || '',
                binary: !!binary,
            };
            return file;
        },
        append: (fileName, content) =>
            defaultFetchEvent(fetchEventUtils.file.defaultEvent('append', fileName, content)),
        write: (fileName, content, binary) =>
            defaultFetchEvent(fetchEventUtils.file.defaultEvent('write', fileName, content, binary)),
        read: (fileName, content, binary) =>
            defaultFetchEvent(fetchEventUtils.file.defaultEvent('read', fileName, content, binary)),
        exists: fileName =>
            defaultFetchEvent(fetchEventUtils.file.defaultEvent('read', fileName)),
        existsWithReadOrCreate: (fileName, content) =>
            defaultFetchEvent(fetchEventUtils.file.defaultEvent('existsWithReadOrCreate', fileName, content)),
        copyFile: (src, dist) => {
            const file = fetchEvent.fetchEventAction.file.copyFile();
            file.param = {
                source: src,
                target: dist,
            };
            return defaultFetchEvent(file);
        },
        copyFileWithReplace: (src, dist, replaceField, replaceContent) => {
            const file = fetchEvent.fetchEventAction.file.copyFileWithReplace();
            file.param = {
                source: src,
                target: dist,
                replaceField: replaceField || '',
                replaceContent: replaceContent || '',
            };
            return defaultFetchEvent(file);
        },
    },
    os: {
        get: () => defaultFetchEvent(fetchEvent.fetchEventAction.os.get),
    },
    request: {
        defaultEvent: (eventName, url, form, header) => {
            const req = fetchEvent.fetchEventAction.request[eventName]();
            req.param = {
                url,
                form: form || {},
                header: header || {},
            };
            return req;
        },
        get: (url, form, header) => defaultFetchEvent(fetchEventUtils.request.defaultEvent('get', url, form, header)),
        post: (url, form, header) => defaultFetchEvent(fetchEventUtils.request.defaultEvent('post', url, form, header)),
    },
    command: {
        copyDir: (src, dist) => {
            const cmd = fetchEvent.fetchEventAction.command.copyDir();
            cmd.param = {
                source: src,
                target: dist,
            };
            return defaultFetchEvent(cmd);
        },
    },
    browserView: {
        openBrowserView(width, height, frame, modal, url, closeUrl) {
            const browser = fetchEvent.fetchEventAction.browserView.openBrowserView();
            browser.param = { width, height, frame, modal, url, closeUrl };
            return defaultFetchEvent(browser);
        },
    },
    spawn: {
        runCommand(command, args) {
            const spawn = fetchEvent.fetchEventAction.spawn.runCommand();
            spawn.param = { command, args };
            return defaultFetchEvent(spawn);
        },
    },
    mysql: {
        checkConfig: () => defaultFetchEvent(fetchEvent.fetchEventAction.mysql.checkConfig()),
        checkConnection: () => defaultFetchEvent(fetchEvent.fetchEventAction.mysql.checkConnection()),
        query: (sql) => {
            const query = fetchEvent.fetchEventAction.mysql.query();
            query.param.sql = sql;
            return defaultFetchEvent(query);
        },
        configPath: () => defaultFetchEvent(fetchEvent.fetchEventAction.mysql.configPath()),
    },
    __config__,
    MDialog: {
        getFile(title, defaultPath, buttonLabel, filters) {
            const obj = {};
            title ? obj.title = title : false;
            defaultPath ? obj.defaultPath = defaultPath : false;
            buttonLabel ? obj.buttonLabel = buttonLabel : false;
            filters ? obj.filters = filters : false;
            return defaultFetchEvent(Object.assign(
                fetchEvent.fetchEventAction.MDialog.getFile(), {
                    param: obj,
                },
            ));
        },
        getDir(title, defaultPath, buttonLabel) {
            const obj = {};
            title ? obj.title = title : false;
            defaultPath ? obj.defaultPath = defaultPath : false;
            buttonLabel ? obj.buttonLabel = buttonLabel : false;
            return defaultFetchEvent(Object.assign(
                fetchEvent.fetchEventAction.MDialog.getDir(), {
                    param: obj,
                },
            ));
        },
        getSaveFile(title, defaultPath, buttonLabel, filters) {
            const obj = {};
            title ? obj.title = title : false;
            defaultPath ? obj.defaultPath = defaultPath : false;
            buttonLabel ? obj.buttonLabel = buttonLabel : false;
            filters ? obj.filters = filters : false;
            return defaultFetchEvent(Object.assign(
                fetchEvent.fetchEventAction.MDialog.getSaveFile(), {
                    param: obj,
                },
            ));
        },
        getSaveDir(title, defaultPath, buttonLabel) {
            const obj = {};
            title ? obj.title = title : false;
            defaultPath ? obj.defaultPath = defaultPath : false;
            buttonLabel ? obj.buttonLabel = buttonLabel : false;
            return defaultFetchEvent(Object.assign(
                fetchEvent.fetchEventAction.MDialog.getSaveDir(), {
                    param: obj,
                },
            ));
        },
    },
    dialog: {
        getFile(title, defaultPath, buttonLabel, filters) {
            const obj = {};
            title ? obj.title = title : false;
            defaultPath ? obj.defaultPath = defaultPath : false;
            buttonLabel ? obj.buttonLabel = buttonLabel : false;
            filters ? obj.filters = filters : false;
            return onlySuccessPromise(fetchEvent.dialog.getFile, [obj]);
        },
        getDir(title, defaultPath, buttonLabel) {
            const obj = {};
            title ? obj.title = title : false;
            defaultPath ? obj.defaultPath = defaultPath : false;
            buttonLabel ? obj.buttonLabel = buttonLabel : false;
            return onlySuccessPromise(fetchEvent.dialog.getDir, [obj]);
        },
        getSaveFile(title, defaultPath, buttonLabel, filters) {
            const obj = {};
            title ? obj.title = title : false;
            defaultPath ? obj.defaultPath = defaultPath : false;
            buttonLabel ? obj.buttonLabel = buttonLabel : false;
            filters ? obj.filters = filters : false;
            return onlySuccessPromise(fetchEvent.dialog.getSaveFile, [obj]);
        },
        getSaveDir(title, defaultPath, buttonLabel) {
            const obj = {};
            title ? obj.title = title : false;
            defaultPath ? obj.defaultPath = defaultPath : false;
            buttonLabel ? obj.buttonLabel = buttonLabel : false;
            return onlySuccessPromise(fetchEvent.dialog.getSaveDir, [obj]);
        },
    },
    plugin: {
        excel: {
            writeExcel(filename, results, rowHeight) {
                const wxlsx = fetchEvent.fetchEventAction.excel.writeExcel();
                wxlsx.param = {
                    filename,
                    results,
                    rowHeight,
                };
                return defaultFetchEvent(wxlsx);
            },
            writeCSV(filename, results) {
                const wcsv = fetchEvent.fetchEventAction.excel.writeCSV();
                wcsv.param.filename = filename;
                wcsv.param.results = results;
                return defaultFetchEvent(wcsv);
            },
            readExcel(filename, header) {
                const rxlsx = fetchEvent.fetchEventAction.excel.readExcel();
                rxlsx.param = {
                    filename,
                    header,
                };
                return defaultFetchEvent(rxlsx);
            },
            readCSV(filename) {
                const rcsv = fetchEvent.fetchEventAction.excel.readCSV();
                rcsv.param.filename = filename;
                return defaultFetchEvent(rcsv);
            },
            dbToExcel(filename, sql, keyLabel, sheetName) {
                const rcsv = fetchEvent.fetchEventAction.excel.dbToExcel();
                rcsv.param = {
                    filename,
                    sql,
                    keyLabel,
                    sheetName,
                };
                return defaultFetchEvent(rcsv);
            },
        },
    },
};
